package com.repro.baselib.lib_base.network.interceptors;


import android.text.TextUtils
import com.repo.utils.DLog
import com.repro.baselib.lib_base.constant.RetroNetConstant
import com.repro.baselib.lib_base.utils.AppInfoUtil
import com.repro.lib_base.utils.Md5Util
import okhttp3.FormBody
import okhttp3.Interceptor
import okhttp3.Response
import org.json.JSONArray
import org.json.JSONObject
import org.json.JSONTokener
import java.lang.Exception
import java.net.URLDecoder
import java.net.URLEncoder
import java.util.*
import kotlin.Comparator
import kotlin.collections.LinkedHashMap

/**
 * 构造自己的请求头及加密方式
 */
class HahaRequestInterceptor : Interceptor {

    private var encodeValue: String = ""
    private var decodeValue: String = ""
    private var md5Sign: String = ""

    companion object {
        private var appVersionCode = AppInfoUtil.getVersionCode()
        private var channel = AppInfoUtil.getChannel()
        private var appId = AppInfoUtil.appId
        private var deviceInfo = AppInfoUtil.getDeviceInfo()
        private var androidOS = AppInfoUtil.getAndroidOS()

    }

    override fun intercept(chain: Interceptor.Chain): Response {
        /**
         * 加密前的原始字符
         */
        var originString = ""

        /**
         *地址拼接的参数key和value集合
         */
        val requestUrlParams = TreeMap<String, String>(Comparator { o1, o2 -> o1.compareTo(o2) })

        val params = TreeMap<String, String>(Comparator { o1, o2 -> o1.compareTo(o2) })
        //参数不排序
        val bodyParams = LinkedHashMap<String, String>()

        val requestT = chain.request()
        val headIgnoreParamsFormat = (requestT.header("IgnoreParamsArrayFormat")) == ("1")

        /**
         * 获取地址拼接参数集合
         */
        collectRequestParams(requestUrlParams, requestT.url.toString())
        /**
         *BODY参数集合
         *body转成json
         */
        if (requestT.body == null) {
            //空对象{}
            params["param"] = JSONObject().toString()
        } else {
            requestT.body?.let {
                if (it is FormBody) {
                    if (it.size == 0) {
                        //空对象{}
                        params["param"] = JSONObject().toString()
                    } else {
                        val jsonObject = JSONObject()
                        for (i in 0 until it.size) {
                            encodeValue = it.encodedValue(i)
                            decodeValue = URLDecoder.decode(encodeValue, "UTF-8")
                            if (!TextUtils.isEmpty(decodeValue)) {
                                val next = (JSONTokener(decodeValue).nextValue())
                                if (next is JSONArray && !headIgnoreParamsFormat) {
                                    val jsonArray = JSONArray(decodeValue)
                                    bodyParams[it.encodedName(i)] = jsonArray.toString()
                                } else {
                                    bodyParams[it.encodedName(i)] = decodeValue
                                }
                            }else{
                                bodyParams[it.encodedName(i)] = ""
                            }
                        }
                        for (key in bodyParams.keys) {
                            jsonObject.put(key, bodyParams[key])
                        }
                        params["param"] = jsonObject.toString()
                    }
                } else {
                    params["param"] = JSONObject().toString()
                }
            }
        }

        /**
         * 原始字符拼接
         * Urlencode之后的字符串
         */
        originString = jointString(requestUrlParams, params)
        md5Sign = Md5Util.generateKd(Md5Util.md5Hex(originString), appId, appVersionCode, channel)

        /**
         * 请求头默认参数
         * X-APP-CHANNEL 渠道号
         * X-APP-ID  APPID
         * X-APP-VERSION 应用版本号 versioncode
         * X-Authorization 用户Token
         * X-Uid  用户id
         * X-Device-IMEI 设备唯一标识
         * X-Language APP当前语言
         * X-Device-Model 设备型号
         * X-OS Android版本
         */
        val request = chain.request().newBuilder()
            .addHeader("Content-Type", "application/json;charset=UTF-8")
            .addHeader("X-APP-CHANNEL", channel)
            .addHeader("X-APP-ID", appId)
            .addHeader("X-APP-VERSION", appVersionCode)
            .addHeader("X-Authorization", RetroNetConstant.testToken ?: "")
            .addHeader("X-Uid", RetroNetConstant.testId ?: "")
            .addHeader("X-Device-IMEI", AppInfoUtil.getDeviceIMEI())
            .addHeader("X-Language", AppInfoUtil.getLanguageCode())
            .addHeader("X-Device-Model", URLEncoder.encode(deviceInfo, "utf-8"))
            .addHeader("X-OS", URLEncoder.encode(androidOS, "utf-8"))
            .addHeader("X-Sign", md5Sign)
            .build()
        return chain.proceed(request)
    }

    private fun collectRequestParams(map: TreeMap<String, String>, url: String) {
        if (url.indexOf('?') != -1) {
            val contents = url.substring(url.indexOf('?') + 1)
            val keyValues = contents.split("&")
            try {
                keyValues.forEachIndexed { index, _ ->
                    val key = keyValues[index].substring(0, keyValues[index].indexOf("="))
                    val value = keyValues[index].substring(keyValues[index].indexOf("=") + 1)
                    map[key] = value
                }
            } catch (e: Exception) {
                DLog.d("请求参数格式有问题")
            }

        }
    }


    /**
     * 参数拼接
     * @param map get url连接params
     * @param postParams body params
     */
    private fun jointString(
        map: TreeMap<String, String>,
        postParams: TreeMap<String, String>
    ): String {
        val origin = StringBuffer()
        //拼接token
        origin.append(RetroNetConstant.testToken ?: "")
        //get 拼接参数
        if (map.size == 0) {
            origin.append("|")
        } else {
            map.forEach {
                origin.append("|${it.value}")
            }
        }

        //post 拼接body
        origin.append("|${postParams["param"]}")
        return URLEncoder.encode(origin.toString(), "utf-8")
    }
}
